#!/bin/bash

size=10
max=10
hitchar='X'
misschar=' '

function disk_width() { echo $(($1*2+1)); }
width=`disk_width $max`

function top()  { eval echo '${'$1'[@]:${#'$1'[@]}-1'}; }
function pop()  { eval $1='(${'$1'[@]:0:${#'$1'[@]}-1})'; }
function push() { eval $1='(${'$1'[@]}' $2')'; }
function move() { t=`top $1`; pop $1; push $2 $t; }
function index(){ eval echo '${'$1'[$2]}'; }
function size() { eval echo '${#'$1'[*]}'; }

declare -a disks
for ((i=0; i<=size; i++)) ; do
    st=$(($width/2-$i))
    en=$(($width/2+$i))
    disk=""
    for ((j=1; j<=width; j++ )) do
	if [[ $j -gt $st && $j -lt $en ]] ; then
	    disk="$disk$hitchar"
	else
	    disk="$disk$misschar"
	fi
    done
    disks[$i]="$disk"
done

function print_pegs() {
    local i line w page
    for ((i=$max; i>=0; i--)) ; do 
	line=""
	for peg in $pegs ; do 
	    w=0
	    if [ `size $peg` -gt $i ] ; then
		w=`index $peg $i`
	    fi
	    line="$line${disks[$w]}"
	done
	page="$page$line\n"
    done
    clear
    echo -e "$page"
}

function hanoi() {
    local n=$1 f=$2 t=$3 u=$4
    if [ $n -le "1" ] ; then
	move $f $t
	print_pegs
    else
	hanoi $((n-1)) $f $u $t
	hanoi 1 $f $t $u
	hanoi $((n-1)) $u $t $f
    fi
}

declare -a a b c
eval a=\( {$size..1} \)
pegs="a b c"

print_pegs
while : ; do 
    sleep 1
    hanoi $size a b c
    sleep 1
    hanoi $size b c a
    sleep 1
    hanoi $size c a b
done
